package com.rtsapp.naval.version;

import com.rtsapp.naval.version.context.VersionContext;
import com.rtsapp.tank2d.config.ConfigHub;

import org.apache.jasper.servlet.JspServlet;
import org.apache.log4j.PropertyConfigurator;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.eclipse.jetty.server.*;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

import java.io.File;
import java.io.IOException;
import java.net.URL;

public class JettyServerStart {

    private static final Logger LOGGER = LoggerFactory.getLogger(JettyServerStart.class);

    private static final String CONTEXT_PATH = "/";
    private static final String CONFIG_LOCATION_PACKAGE = "com.rtsapp.naval.version.config";
    private static final String MAPPING_URL = "/";
    private static final String WEBAPP_DIRECTORY = "webapp";

    public static void main(String[] args) throws Exception {

        ConfigHub.config(args);

        URL url = JettyServerStart.class.getClassLoader().getResource("log4j.properties");
        PropertyConfigurator.configure(url);

        int port = 80;
        boolean isSSL = false;
        int sslPort = 80;
        String key = "";
        String path = "";
        try {
            SAXReader saxReader = new SAXReader();
            Document dom = saxReader.read(new File("cfg/config.xml"));
            Element root = dom.getRootElement();
            Element server = root.element("server");
            Element ssl = root.element("ssl");
            Element keystore = root.element("keystore");

            if (server != null) {
                port = Integer.valueOf(server.attributeValue("port"));
                isSSL = Boolean.valueOf(ssl.attributeValue("open"));
                sslPort = Integer.valueOf(ssl.attributeValue("port"));
                key = keystore.attributeValue("key");
                path = keystore.attributeValue("path");
            }

        } catch (DocumentException e) {
            e.printStackTrace();
        }

        VersionContext.initVersionInfo();

        new JettyServerStart().startJetty(port, isSSL, sslPort, key, path);

    }

    private static ServletContextHandler getServletContextHandler() throws IOException {
        ServletContextHandler contextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS); // SESSIONS requerido para JSP
        contextHandler.setErrorHandler(null);

//        contextHandler.setResourceBase(new ClassPathResource(WEBAPP_DIRECTORY).getURI().toString());
//        contextHandler.setContextPath(CONTEXT_PATH);

        // JSP
        contextHandler.setClassLoader(Thread.currentThread().getContextClassLoader()); // Necesario para cargar JspServlet
        contextHandler.addServlet(JspServlet.class, "*.jsp");

        // Spring
        WebApplicationContext webAppContext = getWebApplicationContext();
        DispatcherServlet dispatcherServlet = new DispatcherServlet(webAppContext);
        ServletHolder springServletHolder = new ServletHolder("mvc-dispatcher", dispatcherServlet);
        contextHandler.addServlet(springServletHolder, MAPPING_URL);
        contextHandler.addEventListener(new ContextLoaderListener(webAppContext));

//        FilterHolder filterHolder = new FilterHolder( LoginController.createLoginFilter() );
//        contextHandler.addFilter( filterHolder, ADMIN_ROOT, null );

        return contextHandler;
    }

    private static WebApplicationContext getWebApplicationContext() {
        AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
        context.setConfigLocation(CONFIG_LOCATION_PACKAGE);
        return context;
    }

    private void startJetty(int port, boolean isSSL, int sslPort, String key, String path) throws Exception {

        URL url = JettyServerStart.class.getClassLoader().getResource("log4j.properties");
        PropertyConfigurator.configure(url);


        LOGGER.debug("Starting server at port {}", port);


        System.out.println("port=" + port + ", isSSL=" + isSSL + ", sslPort=" + sslPort);

        if (isSSL) {
            Thread sslThread = new Thread() {
                @Override
                public void run() {
                    Server sslServer = new Server();

                    HttpConfiguration https_config = new HttpConfiguration();
                    https_config.setSecureScheme("https");

                    SslContextFactory sslContextFactory = new SslContextFactory();
                    sslContextFactory.setKeyStorePath(path);
                    // 私钥
                    sslContextFactory.setKeyStorePassword(key);
                    // 公钥
                    sslContextFactory.setKeyManagerPassword(key);

                    ServerConnector httpsConnector = new ServerConnector(sslServer,
                            new SslConnectionFactory(sslContextFactory, "http/1.1"),
                            new HttpConnectionFactory(https_config));
                    // 设置访问端口
                    httpsConnector.setPort(sslPort);
//                    httpsConnector.setIdleTimeout(500000);
                    sslServer.addConnector(httpsConnector);

                    try {
                        sslServer.setHandler(getServletContextHandler());

//        addRuntimeShutdownHook(server);

                        sslServer.start();
                        LOGGER.info("SSLServer started at port {}", sslPort);
                        sslServer.join();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                }
            };
            sslThread.start();
        }
        Server server = new Server(port);

        server.setHandler(getServletContextHandler());

//        addRuntimeShutdownHook(server);

        server.start();
        LOGGER.info("Server started at port {}", port);
        server.join();

    }

}
